package ldh.maker.freemaker;

import ldh.bean.util.BeanInfoUtil;
import ldh.bean.util.ValidateUtil;
import ldh.common.json.ValuedEnumObjectSerializer;
import ldh.database.Column;
import ldh.database.Table;
import ldh.maker.util.EnumFactory;
import ldh.maker.util.FreeMakerUtil;

import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public abstract class BeanMaker<T> extends FreeMarkerMaker<T> {

	protected String pack;
	protected String className;
	protected Set<String> imports = new TreeSet<String>();
	
	protected String extendsClassName;
	protected Class<?> extendsClass;
	protected Set<String> implementList = new HashSet<String>();
	protected boolean serializable = false;
	
	protected Table table;
	
	protected Class<?> keyClass; //主键
	protected BeanMaker<?> keyBeanMaker; // 主键maker;
	protected Integer treeId;
	protected String dbName;
	
	@SuppressWarnings("unchecked")
	public T key(Class<?> keyClass, BeanMaker<?> keyBeanMaker) {
		if (keyClass != null) {
			this.keyClass = keyClass;
			imports.add(keyClass.getName());
		} else if (keyBeanMaker != null) {
			this.keyBeanMaker = keyBeanMaker;
			imports.add(keyBeanMaker.getName());
		}
		
		return (T) this;
	}
	
	@SuppressWarnings("unchecked")
	public T table(Table table) {
		this.table = table;
		return (T) this;
	}
	
	@SuppressWarnings("unchecked")
	public T imports(Class<?> clazz) {
		imports.add(clazz.getName());
		return (T) this;
	}

	public T treeId(Integer treeId) {
		this.treeId = treeId;
		return (T) this;
	}

	public T dbName(String dbName) {
		this.dbName = dbName;
		return (T) this;
	}
	
	@SuppressWarnings("unchecked")
	public T imports(BeanMaker<?> maker) {
		if (maker != null) {
			imports.add(maker.getName());
		}
		return (T) this;
	}
	
	@SuppressWarnings("unchecked")
	public T implement(Class<?> clazz) {
		implementList.add(clazz.getName());
		boolean t = BeanInfoUtil.isSerializable(clazz);
		if (t) serializable = true;
		return (T) this;
	}
	
	@SuppressWarnings("unchecked")
	public T className(String className) {
		this.className = className;
		return (T) this;
	}
	
	@SuppressWarnings("unchecked")
	public T pack(String pack) {
		this.pack = pack;
		return (T) this;
	}
	
	@SuppressWarnings("unchecked")
	public T extend(Class<?> extendsClass, String extendsClassName) {
		if (extendsClass != null) {
			this.extendsClassName = extendsClassName;
		}
		if (ValidateUtil.notEmpty(extendsClassName)) {
			extend(extendsClass);
		}
		return (T) this;
	}
	
	@SuppressWarnings("unchecked")
	public T extend(Class<?> extendsClass) {
		imports.add(extendsClass.getName());
		this.extendsClass = extendsClass;
		this.extendsClassName = extendsClass.getName();
		return (T) this;
	}
	
	@SuppressWarnings("unchecked")
	public T extend(BeanMaker<?> beanMaker) {
		imports.add(beanMaker.getName());
		this.extendsClassName = beanMaker.getSimpleName();
		
		return (T) this;
	}
	
	public String getName() {
		String name = pack + "." + className;
		return name;
	}
	
	public String getSimpleName() {
		return className;
	}
	
	public boolean isSerializable() {
		if (serializable) return true;
		if (extendsClass != null) {
			boolean t = BeanInfoUtil.isSerializable(extendsClass);
			if (t) {
				serializable = true;
			}
		}
		return serializable;
	}

	protected void handleEnum() {
		for (Column column : table.getColumnList()) {
			if (FreeMakerUtil.isEnum(column)) {
				String keyId = treeId + "_" + dbName + "_" + table.getName() + "_" + column.getName();
				EnumStatusMaker enumStatusMaker = EnumFactory.getInstance().get(keyId);
				imports.add(enumStatusMaker.getPack() + "." + column.getJavaType());
				imports.add(ValuedEnumObjectSerializer.class.getName());
			}
		}
	}
	
	public void data() {
		check();

		data.put("package", pack);
		data.put("className", className);
		data.put("serializable", isSerializable());
		
		if (keyClass != null) {
			data.put("key", keyClass.getSimpleName());
		} else if (keyBeanMaker != null) {
			data.put("key", keyBeanMaker.getSimpleName());
		}
		
		data.put("table", table);
		
//		data.put("config", MakerConfig.getInstance());
		
		if (extendsClassName != null) data.put("extend", extendsClassName);
		if (implementList.size() > 0) data.put("implements", implementList);
		if (imports.size() > 0) data.put("imports", FreeMakerUtil.imports(imports));
	}
	
	protected void check() {
		if (className == null || className.trim().equals("")) {
			throw new NullPointerException("className must not be null");
		}
		if (fileName == null || fileName.trim().equals("")) {
			fileName = className + ".java";
		}
		super.check();
		if (pack == null && pack.trim().equals("")) {
			throw new NullPointerException("package must not be null");
		}
		
	}
	
	public static void main(String[] args) {
//		String outPath = "E:\\project\\eclipse\\datacenter\\website_statistics\\admin\\src\\main\\base\\ldh\\base\\make\\freemaker";
//		MyMapper other = new MyMapper();
//		other.table("scenic").other("status", Status.class);
//		TableInfo mi = new TableInfo(other);
//		
//		Table table = mi.getTable("scenic");
		
//		BeanMaker bm = new BeanMaker()
//		 	.pack("ldh.base.make.freemaker")
//		 	.extend(CommonEntity.class, "CommonEntity<Integer>")
//		 	.outPath(outPath)
//		 	.make();
//		
//		
//		new BeanWhereMaker()
//		 	.pack("ldh.base.make.freemaker")
//		 	.outPath(outPath)
//		 	.className(FreeMakerUtil.beanName(table.getName()) + "Where")
//		 	.extend(FreeMakerUtil.beanName(table.getName()))
//		 	.imports(bm.getName())
//		 	.implement(Pageable.class)
//		 	.serializable(bm.isSerializable())
//		 	.make();
//		
	}
}
